package com.cjb.cloudfabric.config;

import com.cjb.cloudfabric.entity.FabricUser;
import org.hyperledger.fabric.gateway.*;
import org.hyperledger.fabric.sdk.Enrollment;
import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.security.CryptoSuite;
import org.hyperledger.fabric.sdk.security.CryptoSuiteFactory;
import org.hyperledger.fabric_ca.sdk.EnrollmentRequest;
import org.hyperledger.fabric_ca.sdk.HFCAClient;
import org.hyperledger.fabric_ca.sdk.RegistrationRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.nio.file.Paths;
import java.security.PrivateKey;
import java.util.Properties;
import java.util.Set;

/**
 * @Author chenjinbin
 * @Package IntelliJ IDEA
 * @Class ConnectGateWay
 * @Date 2023-10-08 下午8:41
 */
@Component
@Service
public class ConnectGateWay {
    /**
     * 日志
     */
    private final static Logger log = LoggerFactory.getLogger(ConnectGateWay.class);
    /**
     * 组织1证书
     */
    @Value("${fabric.config-path.org1cert}")
    private String org1Cert;
    /**
     * 钱包快捷路径
     */
    @Value("${fabric.basic-wallet}")
    private String walletPath;


    /**
     * 注册管理员 -- 默认
     *
     * @Author chenjinbin
     * @Value
     * @Title
     */
    public void EnrollAdmin() throws Exception {
        Properties props = new Properties();
        props.put("pemFile",
                org1Cert);
        props.put("allowAllHostNames", "true");
        log.info("打印org1Cert路径 {}", org1Cert);
        log.info("钱包路径 {}", walletPath);
        HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props);
        CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
        caClient.setCryptoSuite(cryptoSuite);

        // Create a wallet for managing identities
        Wallet wallet = Wallets.newFileSystemWallet(Paths.get(walletPath));

        // Check to see if we've already enrolled the admin user.
        if (wallet.get("admin") != null) {
            log.info("An identity for the admin user \"admin\" already exists in the wallet");
            log.info("----------------------------------");
            log.info(wallet.get("admin").toString());
            log.info("----------------------------------");
            return;
        }

        // Enroll the admin user, and import the new identity into the wallet.
        final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest();
        enrollmentRequestTLS.addHost("localhost");
        enrollmentRequestTLS.setProfile("tls");
        Enrollment enrollment = caClient.enroll("admin", "adminpw", enrollmentRequestTLS);
        Identity user = Identities.newX509Identity("Org1MSP", enrollment);
        wallet.put("admin", user);
        log.info("Successfully enrolled user \"admin\" and imported it into the wallet");
    }

    /**
     * 管理员认可以后 注册附属存证证书
     *
     * @Author chenjinbin
     * @Value
     * @Title
     */
    public void RegisterUser(FabricUser fabricUser) throws Exception {
        // Create a CA client for interacting with the CA.
        Properties props = new Properties();
        props.put("pemFile",
                org1Cert);
        props.put("allowAllHostNames", "true");
        HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props);
        CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
        caClient.setCryptoSuite(cryptoSuite);

        // Create a wallet for managing identities
        Wallet wallet = Wallets.newFileSystemWallet(Paths.get(walletPath));

        // Check to see if we've already enrolled the user.
        if (wallet.get("appUser") != null) {
            log.info("An identity for the user \"appUser\" already exists in the wallet");
            return;
        }

        X509Identity adminIdentity = (X509Identity) wallet.get("admin");
        if (adminIdentity == null) {
            log.info("\"admin\" needs to be enrolled and added to the wallet first");
            return;
        }
        User admin = new User() {
            @Override
            public String getName() {
                return "admin";
            }

            @Override
            public Set<String> getRoles() {
                return null;
            }

            @Override
            public String getAccount() {
                return null;
            }

            @Override
            public String getAffiliation() {
                return "org1.department1";
            }

            @Override
            public Enrollment getEnrollment() {
                return new Enrollment() {
                    @Override
                    public PrivateKey getKey() {
                        return adminIdentity.getPrivateKey();
                    }

                    @Override
                    public String getCert() {
                        return Identities.toPemString(adminIdentity.getCertificate());
                    }
                };
            }

            @Override
            public String getMspId() {
                return "Org1MSP";
            }

        };
        if (fabricUser.getUserName() == null) {
            // Register the user, enroll the user, and import the new identity into the wallet.
            RegistrationRequest registrationRequest = new RegistrationRequest("appUser");
            registrationRequest.setAffiliation("org1.department1");
            registrationRequest.setEnrollmentID("appUser");
            String enrollmentSecret = caClient.register(registrationRequest, admin);
            Enrollment enrollment = caClient.enroll("appUser", enrollmentSecret);
            Identity user = Identities.newX509Identity("Org1MSP", enrollment);
            wallet.put("appUser", user);
            log.info("Successfully enrolled user \"appUser\" and imported it into the wallet");
        } else {
            // Register the user, enroll the user, and import the new identity into the wallet.
            RegistrationRequest registrationRequest = new RegistrationRequest(fabricUser.getUserName());
            registrationRequest.setAffiliation("org1.department1");
            registrationRequest.setEnrollmentID(fabricUser.getUserName());
            String enrollmentSecret = caClient.register(registrationRequest, admin);
            Enrollment enrollment = caClient.enroll(fabricUser.getUserName(), enrollmentSecret);
            Identity user = Identities.newX509Identity("Org1MSP", enrollment);
            wallet.put(fabricUser.getUserName(), user);
            log.info("Successfully enrolled user \"appUser\" and imported it into the wallet");
        }
    }

}
